/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.jxrw.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.handle.Context;
import org.noear.solon.data.annotation.Transaction;
import vip.xiaonuo.biz.modular.jxrw.entity.CourseTable;
import vip.xiaonuo.biz.modular.jxrw.entity.JwJxrwExportResult;
import vip.xiaonuo.biz.modular.jxrw.entity.JwJxrwListExportResult;
import vip.xiaonuo.biz.modular.jzgxx.entity.JwJzgxx;
import vip.xiaonuo.biz.modular.jzgxx.param.JwJzgxxPageParam;
import vip.xiaonuo.biz.modular.jzgxx.service.JwJzgxxService;
import vip.xiaonuo.biz.modular.jzgxx.service.impl.JwJzgxxServiceImpl;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.excel.CommonExcelCustomMergeStrategy;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.biz.modular.jxrw.entity.JwJxrw;
import vip.xiaonuo.biz.modular.jxrw.mapper.JwJxrwMapper;
import vip.xiaonuo.biz.modular.jxrw.param.JwJxrwAddParam;
import vip.xiaonuo.biz.modular.jxrw.param.JwJxrwEditParam;
import vip.xiaonuo.biz.modular.jxrw.param.JwJxrwIdParam;
import vip.xiaonuo.biz.modular.jxrw.param.JwJxrwPageParam;
import vip.xiaonuo.biz.modular.jxrw.service.JwJxrwService;
import vip.xiaonuo.common.util.CommonDbUtil;
import vip.xiaonuo.common.util.CommonDownloadUtil;
import vip.xiaonuo.common.util.CommonResponseUtil;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.enums.SysUserStatusEnum;
import vip.xiaonuo.sys.modular.user.param.SysUserExportParam;
import vip.xiaonuo.sys.modular.user.result.SysUserExportResult;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 教学任务Service接口实现类
 *
 * @author lrw
 * @date  2025/02/09 11:00
 **/
@Slf4j
@Component
public class JwJxrwServiceImpl extends ServiceImpl<JwJxrwMapper, JwJxrw> implements JwJxrwService {

@Inject
JwJzgxxServiceImpl jwJzgxxService;
    Map<Object, Object> weekMap = MapUtil.of(new String[][] {
            {"星期日", "2025-2-16"},//cn.hutool.core.date.DateUtil.parse("2025-2-17", "yyyy-MM-dd")
            {"星期一", "2025-2-17"},
            {"星期二", "2025-2-18"},
            {"星期三", "2025-2-19"},
            {"星期四", "2025-2-20"},
            {"星期五", "2025-2-21"},
            {"星期六", "2025-2-22"},
    });
    Map<Object, Object> weekMap2 = MapUtil.of(new String[][] {
            {"星期日", "7"},
            {"星期一", "1"},
            {"星期二", "2"},
            {"星期三", "3"},
            {"星期四", "4"},
            {"星期五", "5"},
            {"星期六", "6"},
    });
    Date date5_1= DateUtil.parseDate("2025-5-1");
    Date date10_1= DateUtil.parseDate("2025-5-1");
    Map<Object, Object> sjMap1 = MapUtil.of(new String[][] {
            {"1-2", "8:20-10:00"},
            {"3-4", "10:20-12:00"},
            {"5-6", "14:30-16:10"},
            {"7-8", "16:30-18:10"},
            {"9-10", "19:30-21:10"}
    });
    Map<Object, Object> sjMap = MapUtil.of(new String[][] {
            {"1-2", "0"},
            {"3-4", "1"},
            {"5-6", "2"},
            {"7-8", "3"},
            {"9-10", "4"}
    });
    Map<Object, Object> sjMap51 = MapUtil.of(new String[][] {
            {"1-2", "8:20-10:00"},
            {"3-4", "10:20-12:00"},
            {"5-6", "15:00-16:40"},
            {"7-8", "16:50-18:30"},
            {"9-10", "19:30-21:10"}
    });
    /**
     * 教职工清单
     */
    List<JwJzgxx> jwJzgxxList=null;
    /**
     * 教职工工号清单
     */
    List<String> jgzIndex=null;

    /**
     * 公用QueryWrapper
     * @param queryWrapper
     * @param jwJxrwPageParam
     */
    private void jxrwQW(QueryWrapper queryWrapper,JwJxrwPageParam jwJxrwPageParam){
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getXnxq01id())) {
            queryWrapper.eq(JwJxrw::getXnxq01id, jwJxrwPageParam.getXnxq01id());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkbjmc())) {
            queryWrapper.like(JwJxrw::getSkbjmc, jwJxrwPageParam.getSkbjmc());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getKcmc())) {
            queryWrapper.like(JwJxrw::getKcmc, jwJxrwPageParam.getKcmc());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getHbmc())) {
            queryWrapper.like(JwJxrw::getHbmc, jwJxrwPageParam.getHbmc());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkjsjgh())) {
            queryWrapper.like(JwJxrw::getSkjsjgh, jwJxrwPageParam.getSkjsjgh());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkjsmc())) {
            queryWrapper.like(JwJxrw::getSkjsmc, jwJxrwPageParam.getSkjsmc());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSksj())) {
            queryWrapper.like(JwJxrw::getSksj, jwJxrwPageParam.getSksj());
        }
        if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkdd())) {
            queryWrapper.like(JwJxrw::getSkdd, jwJxrwPageParam.getSkdd());
        }

    }
    @Override
    public Page<JwJxrw> page(JwJxrwPageParam jwJxrwPageParam) {
        if(ObjectUtil.isEmpty(jwJxrwPageParam.getXnxq01id())) {
            return null;
        }
        try {
            HikariDataSource ds = CommonDbUtil.getTmpDs("/jwdb.properties");
            FlexGlobalConfig.getDefaultConfig().getDataSource().addDataSource("jw", ds);
            DataSourceKey.use("jw");//使用新的数据源
            QueryWrapper queryWrapper = new QueryWrapper();
            jxrwQW(queryWrapper,jwJxrwPageParam);
            if(ObjectUtil.isAllNotEmpty(jwJxrwPageParam.getSortField(), jwJxrwPageParam.getSortOrder())) {
                CommonSortOrderEnum.validate(jwJxrwPageParam.getSortOrder());
                queryWrapper.orderBy(StrUtil.toUnderlineCase(jwJxrwPageParam.getSortField()),jwJxrwPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()));
            } else {
                queryWrapper.orderBy(JwJxrw::getKkdm);
            }
            return this.page(CommonPageRequest.defaultPage(), queryWrapper);
        }catch (Exception e){
            return null;
        }finally{
            DataSourceKey.clear();
        }
    }

    /**
     * 全体教职工信息及索引（工号）
     */
    public void allJzg(){
        //为了提高匹配职称的效率，一次将所有教职工数据取出，并创建工号索引
        JwJzgxxPageParam jwJzgxxPageParam=new JwJzgxxPageParam();
        //jwJzgxxPageParam.setDqzt("职");存在离职、返聘人员在课表中
        jwJzgxxList=jwJzgxxService.list(jwJzgxxPageParam);
        jgzIndex=CollStreamUtil.toList(jwJzgxxList, JwJzgxx::getJgh);
    }

    /**
     * 导出教育部所需全校课程表
     *
     * @param jwJxrwPageParam
     * @param response
     * @throws IOException
     */
    @Override
    public void exportJxrw(JwJxrwPageParam jwJxrwPageParam, Context response) throws IOException {
        File tempFile = null;
        String xnxq01id="";
        try {
            QueryWrapper queryWrapper = null;
            List<JwJxrw> jxrwList =null;

            try {
                HikariDataSource ds = CommonDbUtil.getTmpDs("/jwdb.properties");
                FlexGlobalConfig.getDefaultConfig().getDataSource().addDataSource("jw", ds);
                DataSourceKey.use("jw");//使用新的数据源
                queryWrapper =new QueryWrapper();
                jxrwQW(queryWrapper,jwJxrwPageParam);
                jxrwList = this.list(queryWrapper);
                if (ObjectUtil.isEmpty(jxrwList)) {
                    throw new CommonException("无数据可导出");
                }

            }catch (Exception e){
                throw new CommonException("未输入查询参数");
            }finally {
                DataSourceKey.clear();
            }

            allJzg();
            List<JwJxrwExportResult> jwJxrwExportResultList =new ArrayList<JwJxrwExportResult>() ;
            for (JwJxrw jwJxrw:jxrwList  ) {//一个人一个班一门课
                CopyOptions options = CopyOptions.create()
                        .setIgnoreProperties("skzc","sksj","skdd");
                /*
                1-16周 <br>1,3,5,7,9,11,13,15周
                1-8周 <br>9-10周 <br>1-7周 <br>8-10周
                 */
                String[] skzclist=jwJxrw.getSkzc().split("<br>");//1~4段
                //星期二 0708节<br>星期二 0708节<br>星期五 0708节<br>星期五 0708节
                String[] sksjlist=jwJxrw.getSksj().split("<br>");
                //公共机房四<br>公共机房四<br>公共机房四<br>公共机房四
                //存在无上课地点
                String[] skddlist=null;
                try {
                    skddlist = jwJxrw.getSkdd().split("<br>");
                }catch (Exception ex){}
                String[] skjsjghlist=jwJxrw.getSkjsjgh().split(",");
                String jgZc="";
                int jg_k=0;

                for(String jgh:skjsjghlist){
                    //log.info(jgh);
                    int index = jgzIndex.indexOf(jgh);//CollStreamUtil.toList(jwJzgxxList, JwJzgxx::getJgh)
                    JwJzgxx jwJzgxx=jwJzgxxList.get(index);
                    if(jg_k>0) jgZc+=",";
                    jgZc+=StrUtil.toStringOrEmpty( jwJzgxx.getJszc());//个别职称为空
                    jg_k++;
                }
                int n=skzclist.length;
                String skdd0="";
                for (int i=0;i<n;i++  ) {//同一时间段
                    String skzc=skzclist[i].replaceAll("周","");
                    List<String> zc1list= StrSplitter.split(skzc, ',', 0, true, true);
                    List<Integer> zc2list=new ArrayList<>();
                    for (String zc1:zc1list ) {//需要上课的周次
                        if(zc1.indexOf("-")>0){
                            String[] zc22=zc1.split("-");
                            for(int j=Convert.toInt(zc22[0]);j<=Convert.toInt(zc22[1]);j++) zc2list.add(j);
                        }else zc2list.add(Convert.toInt(zc1));
                    }
                    //CollUtil.sort(zc2list, CompareUtil.naturalComparator());//不能排序，否则会影响组合星期、地点
                    String sksj=sksjlist[i];
                    String week=StrUtil.sub(sksj,0,3);
                    String skdd="";
                    try {
                        skdd = skddlist[i];//上课地点数量不足
                        skdd0 = skdd;
                    }catch (Exception ex){skdd=skdd0;}
                    //String skjc=sksj.substring(3,4);

                    Integer a=Convert.toInt(StrUtil.sub(sksj,4,6));
                    Integer b=Convert.toInt(StrUtil.sub(sksj,6,8));
                    if(b==null) b=a+1;//存在只上一节课情况
                    String skjc= a+"-"+b;
                    Date skdate= DateUtil.parseDate(weekMap.get(week).toString());
                    for (Integer k:zc2list  ) {
                        //DateTime dt=DateUtil.offsetDay(skdate, (k-1)*7);
                        Date dt = DateUtil.offset(skdate, DateField.DAY_OF_MONTH, (k-1)*7);

                        JwJxrwExportResult jwJxrwExportResult = new JwJxrwExportResult();
                        BeanUtil.copyProperties(jwJxrw, jwJxrwExportResult,options);
                        jwJxrwExportResult.setJszc(jgZc);
                        jwJxrwExportResult.setSkzc(k.toString());
                        jwJxrwExportResult.setSkrq(DateUtil.format(dt, "MM-dd"));
                        jwJxrwExportResult.setSkjc(skjc);
                        //log.info(jwJxrwExportResult.getKcdm()+","+skjc);
                        if(date5_1.compareTo(dt)>0) {//5.1前
                            jwJxrwExportResult.setQzsj(sjMap1.get(skjc).toString());
                        }else
                            jwJxrwExportResult.setQzsj(sjMap51.get(skjc).toString());

                        jwJxrwExportResult.setSkdd(skdd);
                        jwJxrwExportResultList.add(jwJxrwExportResult);
                    }
                }
            }

            // 创建临时文件
            String fileName = xnxq01id+"课表信息清单.xlsx";
            tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);

            // 头的策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 11);
            headWriteCellStyle.setWriteFont(headWriteFont);
            // 水平垂直居中
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 内容的策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 内容背景白色
            contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            WriteFont contentWriteFont = new WriteFont();

            // 内容字体大小
            contentWriteFont.setFontHeightInPoints((short) 10);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //设置边框样式，细实线
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

            // 水平垂直居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle,
                    contentWriteCellStyle);

            // 写excel
            EasyExcel.write(tempFile.getPath(), JwJxrwExportResult.class)
                    // 自定义样式
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    // 自动列宽
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))//new LongestMatchColumnWidthStyleStrategy())
                    // 设置第一行字体
                    .registerWriteHandler(new CellWriteHandler() {
                        @Override
                        public void afterCellDispose(CellWriteHandlerContext context) {
                            WriteCellData<?> cellData = context.getFirstCellData();
                            WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
                            Integer rowIndex = context.getRowIndex();
                            if (rowIndex == 0) {
                                WriteFont headWriteFont = new WriteFont();
                                headWriteFont.setFontName("宋体");
                                headWriteFont.setBold(true);
                                headWriteFont.setFontHeightInPoints((short) 11);
                                writeCellStyle.setWriteFont(headWriteFont);
                            }
                        }
                    })
                    // 设置表头行高
                    .registerWriteHandler(new AbstractRowHeightStyleStrategy() {
                        @Override
                        protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
                            if (relativeRowIndex == 0) {
                                // 表头第一行
                                row.setHeightInPoints(34);
                            } else {
                                // 表头其他行
                                row.setHeightInPoints(30);
                            }
                        }

                        @Override
                        protected void setContentColumnHeight(Row row, int relativeRowIndex) {
                            // 内容行
                            row.setHeightInPoints(20);
                        }
                    })
                    .sheet(xnxq01id+"课表信息")
                    .doWrite(jwJxrwExportResultList);
            CommonDownloadUtil.download(tempFile, response);
        } catch (Exception e) {
            log.error(">>> 课表导出失败：", e);
            CommonResponseUtil.renderError(response, "课表导出失败");
        } finally {
            FileUtil.del(tempFile);

        }
    }

    @Override
    public void exportJxrw4Tea(JwJxrwPageParam jwJxrwPageParam, Context response) throws IOException {
        File tempFile = null;
        String jgh=jwJxrwPageParam.getSkjsjgh();//用于导出教师课表
        String jsmc=jwJxrwPageParam.getSkjsmc();//用于导出教师课表
        String skdd=jwJxrwPageParam.getSkdd();//用于导出教室课表
        String xnxq01id = jwJxrwPageParam.getXnxq01id();//学年学期是必知项
        if(ObjectUtil.isEmpty(xnxq01id)||(ObjectUtil.isEmpty(jgh) && ObjectUtil.isEmpty(jsmc))) {
            return ;
        }
        try {
            QueryWrapper queryWrapper = null;
            List<JwJxrw> jxrwList = null;

            try {
                HikariDataSource ds = CommonDbUtil.getTmpDs("/jwdb.properties");
                FlexGlobalConfig.getDefaultConfig().getDataSource().addDataSource("jw", ds);
                DataSourceKey.use("jw");//使用新的数据源
                queryWrapper = new QueryWrapper();
                queryWrapper.orderBy(JwJxrw::getSksj);//按上课时间排序
                jxrwQW(queryWrapper, jwJxrwPageParam);
                jxrwList = this.list(queryWrapper);
                if (ObjectUtil.isEmpty(jxrwList)) {
                    throw new CommonException("无数据可导出");
                }

            } catch (Exception e) {
                throw new CommonException("未输入查询参数");
            } finally {
                DataSourceKey.clear();
            }

            allJzg();//jwJzgxxList,jzgIndex
            String[][] courseInfo=new String[5][8];
            courseInfo[0][0]="1-2";
            courseInfo[1][0]="3-4";
            courseInfo[2][0]="5-6";
            courseInfo[3][0]="7-8";
            courseInfo[4][0]="9-10";
            List<CourseTable> courseTableList = new ArrayList<CourseTable>();
            for (JwJxrw jwJxrw : jxrwList) {//一个人一个班一门课
                String kcmc=jwJxrw.getKcmc();//课程名称
                String hbmc=jwJxrw.getHbmc();//上课的合班名称
                /*
                1-16周 <br>1,3,5,7,9,11,13,15周
                1-8周 <br>9-10周 <br>1-7周 <br>8-10周
                 */
                String[] skzclist = jwJxrw.getSkzc().split("<br>");//1~4段
                //星期二 0708节<br>星期二 0708节<br>星期五 0708节<br>星期五 0708节
                String[] sksjlist = jwJxrw.getSksj().split("<br>");
                //公共机房四<br>公共机房四<br>公共机房四<br>公共机房四
                //存在无上课地点
                String[] skddlist = null;
                try {
                    skddlist = jwJxrw.getSkdd().split("<br>");
                } catch (Exception ex) {
                }
                //上课教师
                jgh = jwJxrw.getSkjsjgh();//传入参数，可能不完整，故重新获取
                jsmc=jwJxrw.getSkjsmc();
                int n = sksjlist.length;
                String skdd0 = "";
                for (int i = 0; i < n; i++) {//同一上课时间
                    String skzc = skzclist[i];
                    if(skzc.contains("1,3,5,"))skzc="单周";
                    else if(skzc.contains("2,4,6,"))skzc="双周";

                    //CollUtil.sort(zc2list, CompareUtil.naturalComparator());//不能排序，否则会影响组合星期、地点
                    String sksj = sksjlist[i];
                    String week = StrUtil.sub(sksj, 0, 3);

                    try {
                        skdd = skddlist[i];//上课地点数量不足
                        skdd0 = skdd;
                    } catch (Exception ex) {
                        skdd = skdd0;
                    }
                    //String skjc=sksj.substring(3,4);

                    Integer a = Convert.toInt(StrUtil.sub(sksj, 4, 6));
                    Integer b = Convert.toInt(StrUtil.sub(sksj, 6, 8));
                    if (b == null) b = a + 1;//存在只上一节课情况
                    String skjc = a + "-" + b;
                    int jc=Convert.toInt(sjMap.get(skjc));
                    int w = Convert.toInt(weekMap2.get(week));

                    courseInfo[jc][w]=kcmc+"\r\n"+hbmc+"\r\n"+skzc+" "+skdd;

                }
            }
            for(int i=0;i<5;i++) {
                CourseTable courseTable=new CourseTable();
                courseTable.setTimenode(courseInfo[i][0]);
                courseTable.setWeek1(courseInfo[i][1]);
                courseTable.setWeek2(courseInfo[i][2]);
                courseTable.setWeek3(courseInfo[i][3]);
                courseTable.setWeek4(courseInfo[i][4]);
                courseTable.setWeek5(courseInfo[i][5]);
                courseTable.setWeek6(courseInfo[i][6]);
                courseTable.setWeek7(courseInfo[i][7]);
                courseTableList.add(courseTable);
            }
            // 创建临时文件
            String fileName =(jgh+jsmc+"_"+ xnxq01id + "课表.xlsx").replace(",","");//多老师时，不能有逗号
            tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 内容背景白色
            //contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            WriteFont contentWriteFont = new WriteFont();

            // 内容字体大小
            contentWriteFont.setFontHeightInPoints((short) 10);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //设置边框样式，细实线
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

            // 水平垂直居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            contentWriteCellStyle.setWrapped(true);//自动换行
            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(
                    null,contentWriteCellStyle);
            // 写excel
            EasyExcel.write(tempFile.getPath(), CourseTable.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    //.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(28))
                    // 自定义样式
                    .sheet("课表")
                    .doWrite(courseTableList);
            CommonDownloadUtil.download(tempFile, response);
        } catch (Exception e) {
            log.error(">>> 课表导出失败：", e);
            CommonResponseUtil.renderError(response, "课表导出失败");
        } finally {
            FileUtil.del(tempFile);

        }
    }
    @Override
    public void exportJxrw4Room(JwJxrwPageParam jwJxrwPageParam, Context response) throws IOException {
        File tempFile = null;
        String jgh=jwJxrwPageParam.getSkjsjgh();//用于导出教师课表
        String jsmc=jwJxrwPageParam.getSkjsmc();//用于导出教师课表
        String skdd0=jwJxrwPageParam.getSkdd();//用于导出教室课表
        String xnxq01id = jwJxrwPageParam.getXnxq01id();//学年学期是必知项
        if(ObjectUtil.isEmpty(xnxq01id)||ObjectUtil.isEmpty(skdd0)) {
            return ;
        }

        try {
            QueryWrapper queryWrapper = null;
            List<JwJxrw> jxrwList = null;

            try {
                HikariDataSource ds = CommonDbUtil.getTmpDs("/jwdb.properties");
                FlexGlobalConfig.getDefaultConfig().getDataSource().addDataSource("jw", ds);
                DataSourceKey.use("jw");//使用新的数据源
                queryWrapper = new QueryWrapper();
                queryWrapper.orderBy(JwJxrw::getSksj);//按上课时间排序
                jxrwQW(queryWrapper, jwJxrwPageParam);
                jxrwList = this.list(queryWrapper);
                if (ObjectUtil.isEmpty(jxrwList)) {
                    throw new CommonException("无数据可导出");
                }

            } catch (Exception e) {
                throw new CommonException("未输入查询参数");
            } finally {
                DataSourceKey.clear();
            }

            allJzg();//jwJzgxxList,jzgIndex
            String[][] courseInfo=new String[5][8];
            courseInfo[0][0]="1-2";
            courseInfo[1][0]="3-4";
            courseInfo[2][0]="5-6";
            courseInfo[3][0]="7-8";
            courseInfo[4][0]="9-10";
            List<CourseTable> courseTableList = new ArrayList<CourseTable>();
            for (JwJxrw jwJxrw : jxrwList) {//一个人一个班一门课
                String kcmc=jwJxrw.getKcmc();//课程名称
                String hbmc=jwJxrw.getHbmc().replace("班","");//上课的合班名称
                /*
                1-16周 <br>1,3,5,7,9,11,13,15周
                1-8周 <br>9-10周 <br>1-7周 <br>8-10周
                 */
                String[] skzclist = jwJxrw.getSkzc().split("<br>");//1~4段
                //星期二 0708节<br>星期二 0708节<br>星期五 0708节<br>星期五 0708节
                String[] sksjlist = jwJxrw.getSksj().split("<br>");
                //公共机房四<br>公共机房四<br>公共机房四<br>公共机房四
                //存在无上课地点
                String[] skddlist = null;
                try {
                    skddlist = jwJxrw.getSkdd().split("<br>");
                } catch (Exception ex) {
                }
                //上课教师
                jgh = jwJxrw.getSkjsjgh();//传入参数，可能不完整，故重新获取
                jsmc=jwJxrw.getSkjsmc();
                int n = sksjlist.length;
                String skdd = "";
                for (int i = 0; i < n; i++) {//同一上课时间。存在被拆成两段的情况（1-6周 <br>7-10周），暂未处理
                    String skzc = skzclist[i];
                    if(skzc.contains("1,3,5,")){
                        skzc.replace("周","");
                        String[] skzcs=skzc.split(",");
                        skzc=skzcs[0]+"-"+skzcs[skzcs.length-1]+"单周";
                    }
                    else if(skzc.contains("2,4,6,")){
                        skzc.replace("周","");
                        String[] skzcs=skzc.split(",");
                        skzc=skzcs[0]+"-"+skzcs[skzcs.length-1]+"双周";
                    }

                    //CollUtil.sort(zc2list, CompareUtil.naturalComparator());//不能排序，否则会影响组合星期、地点
                    String sksj = sksjlist[i];
                    String week = StrUtil.sub(sksj, 0, 3);

                    try {
                        skdd = skddlist[i];//上课地点数量不足
                    } catch (Exception ex) {
                        skdd = "";
                    }
                    if(!skdd.contains(skdd0))continue;//存在同一课程被安排到不同上课地点，不是搜索的场所

                    Integer a = Convert.toInt(StrUtil.sub(sksj, 4, 6));
                    Integer b = Convert.toInt(StrUtil.sub(sksj, 6, 8));
                    if (b == null) b = a + 1;//存在只上一节课情况
                    String skjc = a + "-" + b;
                    int jc=Convert.toInt(sjMap.get(skjc));
                    int w = Convert.toInt(weekMap2.get(week));

                    courseInfo[jc][w]=kcmc+"\r\n"+hbmc+"\r\n"+skzc+" "+jsmc;

                }
            }
            for(int i=0;i<5;i++) {
                CourseTable courseTable=new CourseTable();
                courseTable.setTimenode(courseInfo[i][0]);
                courseTable.setWeek1(courseInfo[i][1]);
                courseTable.setWeek2(courseInfo[i][2]);
                courseTable.setWeek3(courseInfo[i][3]);
                courseTable.setWeek4(courseInfo[i][4]);
                courseTable.setWeek5(courseInfo[i][5]);
                courseTable.setWeek6(courseInfo[i][6]);
                courseTable.setWeek7(courseInfo[i][7]);
                courseTableList.add(courseTable);
            }
            // 创建临时文件
            String fileName =skdd0+"_"+ xnxq01id + "课表.xlsx";
            tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 内容背景白色
            //contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            WriteFont contentWriteFont = new WriteFont();

            // 内容字体大小
            contentWriteFont.setFontHeightInPoints((short) 10);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //设置边框样式，细实线
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

            // 水平垂直居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            contentWriteCellStyle.setWrapped(true);//自动换行
            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(
                    null,contentWriteCellStyle);
            // 写excel
            EasyExcel.write(tempFile.getPath(), CourseTable.class)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    //.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(28))
                    // 自定义样式
                    .sheet("课表")
                    .doWrite(courseTableList);
            CommonDownloadUtil.download(tempFile, response);
        } catch (Exception e) {
            log.error(">>> 课表导出失败：", e);
            CommonResponseUtil.renderError(response, "课表导出失败");
        } finally {
            FileUtil.del(tempFile);

        }
    }
    /**
     * 导出教育部所需课程清单
     *
     * @param jwJxrwPageParam
     * @param response
     * @throws IOException
     */
    @Override
    public void exportJxrwList(JwJxrwPageParam jwJxrwPageParam, Context response) throws IOException {
        File tempFile = null;
        String xnxq01id="";
        try {
            QueryWrapper queryWrapper = null;
            List<JwJxrw> jxrwList =null;

            try {
                HikariDataSource ds = CommonDbUtil.getTmpDs("/jwdb.properties");
                FlexGlobalConfig.getDefaultConfig().getDataSource().addDataSource("jw", ds);
                DataSourceKey.use("jw");//使用新的数据源
                queryWrapper =new QueryWrapper();
                /*xnxq01id=jwJxrwPageParam.getXnxq01id();
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getXnxq01id())) {
                    queryWrapper.eq(JwJxrw::getXnxq01id, jwJxrwPageParam.getXnxq01id());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkbjmc())) {
                    queryWrapper.like(JwJxrw::getSkbjmc, jwJxrwPageParam.getSkbjmc());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getKcmc())) {
                    queryWrapper.like(JwJxrw::getKcmc, jwJxrwPageParam.getKcmc());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getHbmc())) {
                    queryWrapper.like(JwJxrw::getHbmc, jwJxrwPageParam.getHbmc());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkjsjgh())) {
                    queryWrapper.like(JwJxrw::getSkjsjgh, jwJxrwPageParam.getSkjsjgh());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkjsmc())) {
                    queryWrapper.like(JwJxrw::getSkjsmc, jwJxrwPageParam.getSkjsmc());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSksj())) {
                    queryWrapper.like(JwJxrw::getSksj, jwJxrwPageParam.getSksj());
                }
                if(ObjectUtil.isNotEmpty(jwJxrwPageParam.getSkdd())) {
                    queryWrapper.like(JwJxrw::getSkdd, jwJxrwPageParam.getSkdd());
                }*/
                jxrwQW(queryWrapper,jwJxrwPageParam);
                jxrwList = this.list(queryWrapper);
                if (ObjectUtil.isEmpty(jxrwList)) {
                    throw new CommonException("无数据可导出");
                }

            }catch (Exception e){
                throw new CommonException("未输入查询参数");
            }finally {
                DataSourceKey.clear();
            }

            allJzg();
            List<JwJxrwListExportResult> jwJxrwListExportResultList =new ArrayList<JwJxrwListExportResult>() ;
            for (JwJxrw jwJxrw:jxrwList  ) {//
                //CopyOptions options = CopyOptions.create().setIgnoreProperties("skzc","sksj","skdd");
                String jgZc="";
                if(jwJxrw.getSkjsjgh()!=null) {//存在没有任课老师？？？
                    String[] skjsjghlist = jwJxrw.getSkjsjgh().split(",");
                    int jg_k = 0;
                    for (String jgh : skjsjghlist) {
                        //log.info(jgh);
                        int index = jgzIndex.indexOf(jgh);//
                        JwJzgxx jwJzgxx = jwJzgxxList.get(index);
                        if (jg_k > 0) jgZc += ",";
                        jgZc += StrUtil.toStringOrEmpty(jwJzgxx.getJszc());//个别职称为空
                        jg_k++;
                    }
                }
                JwJxrwListExportResult jwJxrwListExportResult = new JwJxrwListExportResult();
                BeanUtil.copyProperties(jwJxrw, jwJxrwListExportResult);
                if (jwJxrw.getKcxzmc().contains("专业")) jwJxrwListExportResult.setKcxzmc("专业课");
                if (jwJxrw.getKcxzmc().equals("公共课")) {
                    if (jwJxrw.getKcsxmc().contains("必修")) jwJxrwListExportResult.setKcxzmc("公共必修课");
                    else jwJxrwListExportResult.setKcxzmc("公共选修课");
                }
                jwJxrwListExportResult.setJszc(jgZc);
                jwJxrwListExportResultList.add(jwJxrwListExportResult);


            }

            // 创建临时文件
            String fileName = xnxq01id+"课程清单.xlsx";
            tempFile = FileUtil.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);

            // 头的策略
            WriteCellStyle headWriteCellStyle = new WriteCellStyle();
            WriteFont headWriteFont = new WriteFont();
            headWriteFont.setFontHeightInPoints((short) 11);
            headWriteCellStyle.setWriteFont(headWriteFont);
            // 水平垂直居中
            headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 内容的策略
            WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
            // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
            contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            // 内容背景白色
            contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
            WriteFont contentWriteFont = new WriteFont();

            // 内容字体大小
            contentWriteFont.setFontHeightInPoints((short) 10);
            contentWriteCellStyle.setWriteFont(contentWriteFont);

            //设置边框样式，细实线
            contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
            contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
            contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
            contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

            // 水平垂直居中
            contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
            contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle,
                    contentWriteCellStyle);

            // 写excel
            EasyExcel.write(tempFile.getPath(), JwJxrwListExportResult.class)
                    // 自定义样式
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    // 自动列宽
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))
                    // 设置第一行字体
                    .registerWriteHandler(new CellWriteHandler() {
                        @Override
                        public void afterCellDispose(CellWriteHandlerContext context) {
                            WriteCellData<?> cellData = context.getFirstCellData();
                            WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();
                            Integer rowIndex = context.getRowIndex();
                            if (rowIndex == 0) {
                                WriteFont headWriteFont = new WriteFont();
                                headWriteFont.setFontName("宋体");
                                headWriteFont.setBold(true);
                                headWriteFont.setFontHeightInPoints((short) 11);
                                writeCellStyle.setWriteFont(headWriteFont);
                            }
                        }
                    })
                    // 设置表头行高
                    .registerWriteHandler(new AbstractRowHeightStyleStrategy() {
                        @Override
                        protected void setHeadColumnHeight(Row row, int relativeRowIndex) {
                            if (relativeRowIndex == 0) {
                                // 表头第一行
                                row.setHeightInPoints(34);
                            } else {
                                // 表头其他行
                                row.setHeightInPoints(30);
                            }
                        }

                        @Override
                        protected void setContentColumnHeight(Row row, int relativeRowIndex) {
                            // 内容行
                            row.setHeightInPoints(20);
                        }
                    })
                    .sheet(xnxq01id+"课程信息")
                    .doWrite(jwJxrwListExportResultList);
            CommonDownloadUtil.download(tempFile, response);
        } catch (Exception e) {
            log.error(">>> 课程清单导出失败：", e);
            CommonResponseUtil.renderError(response, "课程清单导出失败");
        } finally {
            FileUtil.del(tempFile);

        }
    }
    @Transaction
    @Override
    public void add(JwJxrwAddParam jwJxrwAddParam) {
        JwJxrw jwJxrw = BeanUtil.toBean(jwJxrwAddParam, JwJxrw.class);
        this.save(jwJxrw);
    }

    @Transaction
    @Override
    public void edit(JwJxrwEditParam jwJxrwEditParam) {
        JwJxrw jwJxrw = this.queryEntity(jwJxrwEditParam.getKkdm());
        BeanUtil.copyProperties(jwJxrwEditParam, jwJxrw);
        this.updateById(jwJxrw);
    }

    @Transaction
    @Override
    public void delete(List<JwJxrwIdParam> jwJxrwIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(jwJxrwIdParamList, JwJxrwIdParam::getKkdm));
    }

    @Override
    public JwJxrw detail(JwJxrwIdParam jwJxrwIdParam) {
        return this.queryEntity(jwJxrwIdParam.getKkdm());
    }

    @Override
    public JwJxrw queryEntity(String id) {
        JwJxrw jwJxrw = this.getById(id);
        if(ObjectUtil.isEmpty(jwJxrw)) {
            throw new CommonException("教学任务不存在，id值为：{}", id);
        }
        return jwJxrw;
    }
}
